package com.winter.main.config;

import com.winter.main.exception.BusExceptionHandler;
import com.winter.main.filter.MainFilter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.web.servlet.HandlerExceptionResolver;
import sun.applet.Main;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * Desc:
 * Author: dushuang
 * Date: Create in 2018/4/26
 */
@Configuration
public class ShiroConfig {

    @Value("${spring.redis.database}")
    private int redisDatabase;

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Value("${spring.redis.password}")
    private String redisPassword;

    /**
     * 将自己的验证放入容器
     * @return
     */
    @Bean
    public CustomRealm myShiroRealm(){
        CustomRealm shiroRealm = new CustomRealm();
        return shiroRealm;
    }

    /**
     * 权限管理，配置主要是Realm的管理认证
     * @return
     */
    @Bean(name = "securityManager")
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        // shiro-redis
        securityManager.setCacheManager(redisCacheManager());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }


    /**
     * Filter工厂，设置对应的过滤条件和跳转条件
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        // 自定义filter
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("mainFilter", new MainFilter());

        // 添加过滤规则
        Map<String, String> map = new HashMap<>();
        // 登出
        map.put("/logout","logout");
        // 配置不会被拦截的链接 顺序判断
        map.put("/druid/**", "anon");
        map.put("/static/**", "anon");  // 静态资源不过滤
        map.put("/system/user/login", "anon");
        map.put("/system/user/verifyLogin", "anon");
        map.put("/system/user/index", "authc");
        // 对所有路径认证
        map.put("/**","mainFilter,authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        // 登录
        shiroFilterFactoryBean.setLoginUrl("/system/user/login");
        // 首页
        shiroFilterFactoryBean.setSuccessUrl("/system/user/index");
        // 认证不通的跳转页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/system/user/login");

        return shiroFilterFactoryBean;
    }

    @Bean
    public SimpleCookie simpleCookie(){
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setName("custom.session");
        simpleCookie.setPath("/");
        return simpleCookie;
    }

    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     * @return
     */
    @Bean
    public RedisSessionDAO sessionDAO(){
        RedisSessionDAO sessionDAO = new RedisSessionDAO();
        sessionDAO.setRedisManager(new MyRedisManager());
        sessionDAO.setKeyPrefix("shiro-cache:");
        return sessionDAO;
    }

    /**
     * cacheManager 缓存 redis实现
     * @return
     */
    @Bean
    public RedisCacheManager redisCacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        MyRedisManager redisManager = new MyRedisManager();
        redisManager.setHost(redisHost);
        redisManager.setPassword(redisPassword);
        redisManager.setPort(redisPort);
        redisManager.setDatabase(redisDatabase);
        redisManager.setExpire(60*1);  // 设置权限缓存
        redisCacheManager.setRedisManager(redisManager);
        return redisCacheManager;
    }

    /**
     * Session 管理
     * @return
     */
    @Bean
    public DefaultWebSessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionIdCookie(simpleCookie());
        sessionManager.setGlobalSessionTimeout(1000L*60*30);  // 过期时间 毫秒
        sessionManager.setSessionDAO(sessionDAO());     // session交给redis管理
        return sessionManager;
    }

    /**
     * 加入注解的使用，不加入这个注解不生效
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor attributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        attributeSourceAdvisor.setSecurityManager(securityManager());
        return attributeSourceAdvisor;
    }

    @Bean(name = "busExceptionHandler")
    public HandlerExceptionResolver handlerExceptionResolver() {
        return new BusExceptionHandler();
    }

}
